﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Ckknight.StateMachine
{
    public sealed partial class StateMachine<TState, TTrigger, TModel>
    {
        /// <summary>
        /// Represents a body of data which details all the information about a specific state.
        /// 
        /// All instances of this class are immutable.
        /// </summary>
        internal sealed class StateData
        {
            #region Internal constructor

            /// <summary>
            /// Instantiate a new instance of StateData.
            /// </summary>
            /// <param name="state">The state which this StateData represents</param>
            /// <param name="transitions">A dictionary representing valid triggers which will transition the state to either the same or a differing state</param>
            /// <param name="dynamicTransitions">A dictionary representing valid triggers which will transition to a dynamic state</param>
            /// <param name="ignores">A sequence of triggers that will be ignored when fired on the current state</param>
            /// <param name="onEntries">A sequence of callbacks that will be fired when the current state is entered by any trigger</param>
            /// <param name="onExits">A sequence of callbacks that will be fired when the current state is exited by any trigger</param>
            /// <param name="onEntryFroms">A dictionary of trigger to sequence of callbacks that will be fired when the current state is entered by the paired trigger</param>
            /// <param name="onExitTos">A dictionary of trigger to sequence of callbacks that will be fired when the current state is exited by the paired trigger</param>
            /// <param name="parents">A sequence of all parent states of the current state</param>
            internal StateData(
                TState state,
                FrozenDictionary<TTrigger, KeyValuePair<TState, Func<Transition, bool>>> transitions,
                FrozenDictionary<TTrigger, KeyValuePair<Func<Transition, TState>, Func<Transition, bool>>> dynamicTransitions,
                TTrigger[] ignores,
                Action<Transition>[] onEntries,
                Action<Transition>[] onExits,
                FrozenDictionary<TTrigger, Action<Transition>[]> onEntryFroms,
                FrozenDictionary<TTrigger, Action<Transition>[]> onExitTos,
                TState[] parents)
            {
                State = state;
                Ignores = ignores;
                Transitions = transitions;
                DynamicTransitions = dynamicTransitions;
                OnEntries = onEntries;
                OnExits = onExits;
                OnEntryFroms = onEntryFroms;
                OnExitTos = onExitTos;
                Parents = parents;
            }

            #endregion

            #region Internal fields

            internal readonly TState State;
            internal readonly TTrigger[] Ignores;
            internal readonly FrozenDictionary<TTrigger, KeyValuePair<TState, Func<Transition, bool>>> Transitions;
            internal readonly FrozenDictionary<TTrigger, KeyValuePair<Func<Transition, TState>, Func<Transition, bool>>> DynamicTransitions;
            internal readonly Action<Transition>[] OnEntries;
            internal readonly Action<Transition>[] OnExits;
            internal readonly FrozenDictionary<TTrigger, Action<Transition>[]> OnEntryFroms;
            internal readonly FrozenDictionary<TTrigger, Action<Transition>[]> OnExitTos;
            internal readonly TState[] Parents;

            #endregion
        }
    }
}
